 ---------------------------------------------------------------------------------
  -- Design Name : Control lines
  -- File Name   : IdCtrl.vht
  -- Function    : Create control lines based on opcode
  -- Authors     : Mirko Francuski  2006/0225
  --               Milos Mihajlovic 2006/0039
  -- School      : University of Belgrade
  --               School for Electrical Engineering
  --               Department for Computer Engineering and Information Theory
  -- Subject     : VLSI Computer Systems
---------------------------------------------------------------------------------

library ieee;

use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use work.UserPkg.all;

entity IdCtrl is
  port (
    op:           in  opCode;
    addV:         in std_logic;
    addC:         in std_logic;
    addrType:     out std_logic;
    shifts:       out std_logic;
    immType:      out std_logic_vector(1 downto 0);
    immUse:       out std_logic;
    branchCond:   out std_logic;
    branchAlw:    out std_logic
  );
end entity;

architecture behavioral of IdCtrl is
signal immOp        : std_logic;
signal addrTypeOp   : std_logic;
signal shiftsOp     : std_logic;
signal immTypeOp    : std_logic_vector(1 downto 0);
signal immUseOp     : std_logic;
signal branchCondOp : std_logic;
signal branchAlwOp  : std_logic;

begin

  addrType    <= addrTypeOp;
  shifts      <= shiftsOp;
  immType     <= immTypeOp;
  immUse      <= immUseOp;
  branchCond  <= branchCondOp;
  branchAlw   <= branchAlwOp;


  immOp         <= '1' when (op = OPC_ADDI) or
                            (op = OPC_SUBI) or                              
                            (op = OPC_MOVI) else
                   '0';


  addrTypeOP    <= '1' when op = OPC_LOAD  or 
                            op = OPC_STORE or 
                            branchAlwOp = '1'   else
                   '0';                   
                       
  shiftsOp      <= '1' when op = OPC_SHL   or 
                            op = OPC_SHR   or 
                            op = OPC_SAR   or 
                            op = OPC_ROL   or
                            op = OPC_ROR  else
                   '0';
                   
  immTypeOp     <= "00" when op = OPC_STORE       or
                             branchCondOp = '1' else                      
                   "01" when op = OPC_LOAD        or
                             immOp =        '1'   or
                             branchAlwOp =  '1' else                                       
                   "10";    --shiftsOp
                   
  immUseOp      <= '1'  when immOp     = '1'      or
                             shiftsOp  = '1'    else
                   '0';
    
  branchCondOp  <= '1'  when op = OPC_BEQ  or
                             op = OPC_BNQ  or
                             op = OPC_BLT  or 
                             op = OPC_BGT  or 
                             op = OPC_BLE  or
                             op = OPC_BGE else
                   '0';
                   
  branchAlwOp   <= '1'  when op = OPC_JMP    or 
                             op = OPC_JSR  else
                   '0';
  

  
  /*
  constant OPC_LOAD    : opCode := "000000";
  constant OPC_ADD     : opCode := "000100";
  constant OPC_AND     : opCode := "000010";
  constant OPC_SHL     : opCode := "000110";
  constant OPC_JMP     : opCode := "000001";
  constant OPC_BEQ     : opCode := "000101";
  constant OPC_HALT    : opCode := "000011";
  constant OPC_STORE   : opCode := "100000";
  constant OPC_SUB     : opCode := "100100";
  constant OPC_OR      : opCode := "100010";
  constant OPC_SHR     : opCode := "100110";
  constant OPC_JSR     : opCode := "100001";
  constant OPC_BNQ     : opCode := "100101";
  constant OPC_XOR     : opCode := "010010";
  constant OPC_SAR     : opCode := "010110";
  constant OPC_RTS     : opCode := "010001";
  constant OPC_BGT     : opCode := "010101";
  constant OPC_NOT     : opCode := "110010";
  constant OPC_ROL     : opCode := "110110";
  constant OPC_BLT     : opCode := "110101";
  constant OPC_MOV     : opCode := "001000";
  constant OPC_ADDI    : opCode := "001100";
  constant OPC_ROR     : opCode := "001110";
  constant OPC_PUSH    : opCode := "001001";
  constant OPC_BGE     : opCode := "001101";
  constant OPC_MOVI    : opCode := "101000";
  constant OPC_SUBI    : opCode := "101100";
  constant OPC_POP     : opCode := "101001";
  constant OPC_BLE     : opCode := "101101";
  constant OPC_NOP     : opCode := "111111";
  */
  
end architecture;